package com.sbm.datasource.config;

import java.lang.reflect.Field;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;

public class MyBatisConfig
		implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware, BeanNameAware, EnvironmentAware {
	private final static String prefix = "mybatis";
	// 外部使用
	private String typeAliasesPackage;
	private String typeHandlersPackage;
	private String mapperScanPackage;
	// 内部使用
	private String beanName;
	private ApplicationContext applicationContext;
	private Environment environment;

	public String getTypeAliasesPackage() {
		return typeAliasesPackage;
	}

	public void setTypeAliasesPackage(String typeAliasesPackage) {
		this.typeAliasesPackage = typeAliasesPackage;
	}

	public String getTypeHandlersPackage() {
		return typeHandlersPackage;
	}

	public void setTypeHandlersPackage(String typeHandlersPackage) {
		this.typeHandlersPackage = typeHandlersPackage;
	}

	public String getMapperScanPackage() {
		return mapperScanPackage;
	}

	public void setMapperScanPackage(String mapperScanPackage) {
		this.mapperScanPackage = mapperScanPackage;
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		if (applicationContext instanceof ConfigurableApplicationContext) {
			BeanDefinition bean = ((ConfigurableApplicationContext) applicationContext).getBeanFactory()
					.getBeanDefinition(beanName);
			DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
			factory.registerBeanDefinition(beanName, bean);
			this.setFieldValue("typeAliasesPackage");
			this.setFieldValue("typeHandlersPackage");
			this.setFieldValue("mapperScanPackage");
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}

	@Override
	public void setBeanName(String name) {
		this.beanName = name;
	}

	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}

	private void setFieldValue(String fieldName) {
		try {
			Field field = this.getClass().getDeclaredField(fieldName);
			boolean accessible = field.isAccessible();
			if (!field.isAccessible()) {
				field.setAccessible(true);
			}
			String value = (String) this.environment.getProperty(prefix + "." + field.getName());
			field.set(this, value);
			field.setAccessible(accessible);
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}
}
